package org.outstudio.antispider;

import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 * @author liuch
 *
 */
public class AntiSpider {
	
	private final Map<String, Queue<Integer>> visitTimeQueueMap = new ConcurrentHashMap<>();
	private final AntiHandler antiHandler;
	private final Integer times;
	private final Integer seconds;
	private final ExecutorService executor = Executors.newCachedThreadPool();

	/**
	 * 构造方法
	 * 
	 * @param antiHandler
	 * 				爬虫处理器
	 * @param times
	 * 				多少次
	 * @param seconds
	 * 				多长时间内
	 */
	public AntiSpider(AntiHandler antiHandler, Integer times, Integer seconds) {
		this.antiHandler = antiHandler;
		this.times = times;
		this.seconds = seconds;
	}

	/**
	 * 当用户访问时，手动调用该方法
	 * 
	 * @param key
	 *            区分用户的唯一标识
	 */
	public void log(String key) {
		Queue<Integer> theQueue = visitTimeQueueMap.get(key);
		if (theQueue == null) {
			Queue<Integer> newQueue = new LinkedList<>();
			theQueue = visitTimeQueueMap.putIfAbsent(key, newQueue);
			if (theQueue == null) {
				theQueue = newQueue;
			}
		}
		synchronized (theQueue) {
			Integer timeNow = (int) (System.currentTimeMillis() / 1000);
			if (theQueue.size() >= times) {
				Integer timePre = theQueue.poll();
				if (timePre - timeNow <= seconds) {
					executor.execute(new Runnable() {
						public void run() {
							antiHandler.doHandle(key);
						}
					});
				}
			}
			theQueue.add(timeNow);
		}
	}
}
